package com.restaurant.application.root.commonui.data;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.nebutown.generation.Convert;
import com.nebutown.generation.PickableBean;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class RowData implements PickableBean {

    public static final String FN_OPERATIONS = "operations";
    public static final String FN_COLUMNS = "columns";

    public static final List<String> FIELD_NAMES = Lists.newArrayList(
            FN_OPERATIONS,
            FN_COLUMNS);

    private Map<String, String> operations;
    private Map<String, CellData> columns;

    public RowData(Map<String, String> operations, Map<String, CellData> columns) {
        setOperations(operations);
        setColumns(columns);
    }

    public RowData() {
    }

    public RowData duplicate() {
        RowData result = new RowData();
        result.operations = this.operations == null ? null : this.operations.keySet().stream().collect(Collectors.toConcurrentMap(e8 -> e8, e8 -> this.operations.get(e8)));
        result.columns = this.columns == null ? null : this.columns.keySet().stream().collect(Collectors.toConcurrentMap(e9 -> e9, e9 -> this.columns.get(e9) == null ? null : this.columns.get(e9).duplicate()));
        return result;
    }

    @Override
    public String toString() {
        return Convert.toJson(this);
    }

    public Map<String, String> getOperations() {
        if (operations == null) {
            operations = Maps.newConcurrentMap();
        }
        return operations;
    }

    public void setOperations(Map<String, String> value) {
        this.operations = value;
    }

    public RowData withOperations(Map<String, String> value) {
        setOperations(value);
        return this;
    }

    public RowData withOperations(Map<String, String> value, Map<String, String> defaultValue) {
        setOperations(value == null ? defaultValue : value);
        return this;
    }

    public RowData putOperations(String key, String value) {
        if (operations == null) {
            operations = Maps.newConcurrentMap();
        }
        this.operations.put(key, value);
        return this;
    }

    public Map<String, CellData> getColumns() {
        if (columns == null) {
            columns = Maps.newConcurrentMap();
        }
        return columns;
    }

    public void setColumns(Map<String, CellData> value) {
        this.columns = value;
    }

    public RowData withColumns(Map<String, CellData> value) {
        setColumns(value);
        return this;
    }

    public RowData withColumns(Map<String, CellData> value, Map<String, CellData> defaultValue) {
        setColumns(value == null ? defaultValue : value);
        return this;
    }

    public RowData putColumns(String key, CellData value) {
        if (columns == null) {
            columns = Maps.newConcurrentMap();
        }
        this.columns.put(key, value);
        return this;
    }

    public Object getValueOf(String name) {
        switch (name) {
            case "operations":
                return getOperations();
            case "columns":
                return getColumns();
        }
        return null;
    }

    public boolean hasField(String name) {
        return FIELD_NAMES.contains(name);
    }

    @Override
    public int hashCode() {
        return signature().hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof RowData)) return false;
        return signature().equals(((RowData) o).signature());
    }

    public String signature() {
        throw new RuntimeException("Bean RowData has no signature defined, no hash code or equals possible.");
    }
}
